﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net.Sockets;
using System.Net;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Configuration;

namespace OfflineSpeechRecognitionMode
{


    /// <summary>
    /// 离线语音模块类
    /// </summary>
    public class OfflineSpeechRecognitionClass
    {


        private Thread listenerThread; // 监听客户端连接的线程
        private Socket serverSocket; // 服务器端Socket对象
        private Socket clientSocket;//客户端Socket对象
        private string logFilePath;//Log日志文件路径


        /// <summary>
        /// 获取监听消息事件
        /// </summary>
        /// <param name="MyMessage">接收到的消息内容，类型为字符串</param>
        public delegate void GetNotifyMessage(string MyMessage);

        /// <summary>
        /// 委托实例变量，用于存储对监听消息事件的引用。
        /// </summary>
        public GetNotifyMessage getNotifyMessage;

        /// <summary>
        /// 存储服务的发来的数据
        /// </summary>
        public string RecieveMessageData = string.Empty;

        /// <summary>
        /// 开启指定的客户端程序
        /// </summary>
        public void StartOfflineSpeechClient()
        {
            try
            {
                // string clientExePath = Path.Combine(System.Environment.CurrentDirectory,ConfigurationManager.AppSettings["exepath"]); 
                string clientExePath = ConfigurationManager.AppSettings["exepath"];
                Process process = new Process();
                try
                {
                    ProcessStartInfo startInfo = new ProcessStartInfo
                    {
                        FileName = clientExePath,
                        UseShellExecute = true,
                        CreateNoWindow = false // 如果你想看到新启动的窗口，可以设置为 false
                    };

                    process.StartInfo = startInfo;
                    process.StartInfo.UseShellExecute = false;
                    process.StartInfo.CreateNoWindow = true;
                    process.Start();

                }
                catch (Exception ex)
                {
                    LogError($"启动程序时出错: {ex.Message}");
                }
            }
            catch { }


        }

        /// <summary>
        /// 关闭指定的客户端程序
        /// </summary>
        public void StopOfflineSpeechClient()
        {
            try
            {
                Process[] processes = Process.GetProcessesByName("core_client");

                foreach (Process process in processes)
                {
                    // 尝试安全关闭进程，例如通过发送信号或消息（取决于你的应用是否有响应）
                    // 这里我们假设它没有提供安全退出的方法，所以直接Kill掉
                    process.CloseMainWindow(); // 先尝试以正常方式关闭主窗口
                    if (!process.WaitForExit(1000)) // 等待最多3秒看是否已退出
                    {
                        process.Kill(); // 如果没有正常退出，则强制终止进程
                    }
                }
            }
            catch (Exception ex)
            {
                LogError($"无法停止进程：{ex.Message}");
            }
        }



        /// <summary>
        /// 发送消息到服务器。
        /// </summary>
        /// <param name="message">要发送的消息。Down 为开始录制，Up为结束录制</param>
        public void SendMessage(string message)
        {
            try
            {
                // 如果客户端Socket对象为null，表示尚未建立连接，则创建新的Socket并连接到服务器
                if (clientSocket == null)
                {
                    // 创建客户端 Socket
                    clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                    clientSocket.Connect(new IPEndPoint(IPAddress.Parse("127.0.0.1"), 8574));
                }

                // 将消息转换为字节数组
                byte[] sendData = Encoding.UTF8.GetBytes(message);
                // 发送消息到服务器
                clientSocket.Send(sendData);
            }
            catch (SocketException ex)
            {
                // 处理连接断开的情况
                LogError($"Socket error: {ex.Message}");
                // 重新连接
                Reconnect();
            }
        }


        /// <summary>
        /// 尝试重新连接客户端套接字到服务器。
        /// </summary>
        private void Reconnect()
        {
            try
            {
                // 创建新的 Socket 对象并连接到服务器。
                clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                clientSocket.Connect(new IPEndPoint(IPAddress.Parse("127.0.0.1"), 8574));
            }
            catch (Exception ex)
            {
                // 处理重新连接失败的情况。您可以在此处添加重试连接或通知用户的逻辑。
                LogError($"重新连接失败: {ex.Message}");
            }
        }

        /// <summary>
        /// 开启监听服务
        /// </summary>
        public void StartListener()
        {
            // 启动监听线程
            listenerThread = new Thread(ListenForClients);
            listenerThread.IsBackground = true; // 将监听线程设置为后台线程，当主线程退出时，该线程也会被终止
            listenerThread.Start();
        }

        /// <summary>
        /// 监听指定的端口和IP
        /// </summary>
        private void ListenForClients()
        {
            try
            {
                // 创建服务器端 Socket 对象
                serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                // 绑定服务器端口
                serverSocket.Bind(new IPEndPoint(IPAddress.Any, 8564));
                // 开始监听客户端连接，设置最大连接数为10
                serverSocket.Listen(10);
                Console.WriteLine("等待客户端连接...");

                while (true)
                {
                    // 接受客户端连接
                    Socket clientSocket = serverSocket.Accept();
                    Console.WriteLine("客户端已连接");

                    // 创建处理客户端连接的线程
                    Thread clientThread = new Thread(() => HandleClient(clientSocket));
                    clientThread.IsBackground = true; // 将客户端处理线程设置为后台线程
                    clientThread.Start(); // 启动客户端处理线程
                    Thread.Sleep(1000);
                }
            }
            catch (Exception ex)
            {
                LogError($"监听时出现错误：{ex.Message}");
            }
        }

        /// <summary>
        /// 处理客户端的连接。
        /// </summary>
        /// <param name="clientSocket">客户端套接字。</param>
        private void HandleClient(Socket clientSocket)
        {
            try
            {
                byte[] buffer = new byte[1024];
                int bytesRead;

                // 循环接收客户端发送的数据
                while ((bytesRead = clientSocket.Receive(buffer)) > 0)
                {
                    // 将接收到的数据转换为字符串
                    string receivedMessage = Encoding.UTF8.GetString(buffer, 0, bytesRead);
                    RecieveMessage(receivedMessage);
                    getNotifyMessage(RecieveMessageData);
                    Thread.Sleep(1000);
                }

                // 关闭客户端连接
                clientSocket.Shutdown(SocketShutdown.Both);
                clientSocket.Close();
            }
            catch (Exception ex)
            {
                // 捕获并记录处理客户端连接时可能出现的异常
                LogError($"处理客户端连接时出错: {ex.Message}");
            }
        }

        /// <summary>
        /// 接受服务端发来的数据信息
        /// </summary>
        /// <returns>服务端发来的数据</returns>
        private string RecieveMessage(string message)
        {
            RecieveMessageData = message;
            return RecieveMessageData;
        }



        /// <summary>
        /// 写入错误日志
        /// </summary>
        /// <param name="errorMessage">错误信息</param>
        private void LogError(string errorMessage)
        {
            // 获取当前执行程序的路径
            string executablePath = AppDomain.CurrentDomain.BaseDirectory;

            // 构造日志文件路径
            logFilePath = Path.Combine(executablePath, "error_log.txt");
            try
            {
                // 格式化错误信息，添加时间戳
                string formattedError = $"{DateTime.Now:yyyy-MM-dd HH:mm:ss} - {errorMessage}";

                // 写入错误信息到日志文件
                using (StreamWriter writer = new StreamWriter(logFilePath, true))
                {
                    writer.WriteLine(formattedError);
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"写入错误日志时出错: {ex.Message}");
            }
        }

        /// <summary>
        /// 读取txt文本
        /// </summary>
        /// <param name="fileName">文件名</param>
        /// <returns></returns>
        private string ReadTextFileContent(string fileName)
        {
            // 获取程序的 bin 目录路径
            string binPath = AppDomain.CurrentDomain.BaseDirectory;
            string remove = "bin\\Debug\\";
            // 获取同级目录的路径
            string parentDirectory = binPath.Replace(remove, "");

            // 获取 txt 文件的完整路径
            string filePath = Path.Combine(parentDirectory, fileName);

            try
            {
                // 使用 StreamReader 打开文本文件并读取内容
                using (StreamReader reader = new StreamReader(filePath))
                {
                    // 读取文本文件的所有内容
                    string content = reader.ReadToEnd();
                    return content;
                }
            }
            catch (Exception ex)
            {
                // 发生异常时输出错误信息并返回空字符串
                LogError($"读取文件时出错: {ex.Message}");
                return string.Empty;
            }
        }




    }
}
